//
// Created by Alex on 2021/9/29.
//

#ifndef COMPILER_SYNTAX_ANALYSIS_H
#define COMPILER_SYNTAX_ANALYSIS_H

#include <utility>

#include "utils.h"

using namespace std;

struct syn_fsm {
private:
    lexical_result lex_res;
    syntax_result *result = nullptr;
    vector<lexical_parse>::iterator sym;
    vector<struct Error> *error = nullptr;
    vector<Scope*> *scope_stack = nullptr;
    vector<Stmt*> *loop_stack = nullptr;
    RetType proc_func_ret_type = INT;
    int curpos = 0;
public:
    explicit syn_fsm(lexical_result _lex_res);
    syntax_result* get_syntax_result();
    static bool check_fmt(lexical_parse* fmt);
private:
    inline lexical_parse parse_at(int i);
    inline lexical_parse* parse();
    CompUnit* get_comp_unit();
    ConstDecl* get_const_decl();
    VarDecl* get_var_decl();
    //MainFuncDef* get_main_func_def();
    FuncDef* get_func_def();
    FuncType* get_func_type();
    FuncFParams* get_func_fparams();
    ConstDef* get_const_def();
    VarDef* get_var_def();
    FuncFParam* get_fparam();
    Block* get_block_normal();
    Block* get_block_paramed(vector<Symbol*> *syms);
    ConstExp* get_const_exp();
    ConstInitVal* get_const_init_val();
    InitVal* get_init_val();
    BlockItem* get_block_item();
    Exp* get_exp();
    Stmt* get_stmt();
    AddExp* get_add_exp();
    IfStmt* get_if_stmt();
    WhileStmt* get_while_stmt();
    BreakStmt* get_break_stmt();
    ContinueStmt* get_continue_stmt();
    ReturnStmt* get_return_stmt();
    PrintfStmt* get_printf_stmt();
    AssignStmt* get_assign_stmt();
    SelectiveExp* get_selective_exp();
    MulExp* get_mul_exp();
    Cond* get_cond();
    LVal* get_lval();
    UnaryExp* get_unary_exp();
    LOrExp* get_lor_exp();
    PrimaryExp* get_primary_exp();
    FuncRParams* get_func_rparams();
    UnaryOp* get_unary_op();
    LAndExp* get_land_exp();
    Number* get_number();
    EqExp* get_eq_exp();
    RelExp* get_rel_exp();
    bool is_exp(int start);
    int pre_read_lval(int start);
    int pre_read_exp(int start);
    int pre_read_add_exp(int start);
    int pre_read_mul_exp(int start);
    int pre_read_unary_exp(int start);
    int pre_read_primary_exp(int start);
    int pre_read_func_rparams(int start);
};

#endif //COMPILER_SYNTAX_ANALYSIS_H
